import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from langchain.agents import tool
from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentType
from langchain_community.llms.tongyi import Tongyi
import os
import json
import time

# 初始化LLM
llm = Tongyi()

# 数据文件路径
DATA_FILE = os.path.join(os.path.dirname(__file__), "data", "user_house_data.csv")
SIMILARITY_CACHE = os.path.join(os.path.dirname(__file__), "data", "user_similarity.json")

# 确保数据目录存在
os.makedirs(os.path.dirname(DATA_FILE), exist_ok=True)

class AIRecommendationTools:
    @staticmethod
    @tool
    def collect_house_data(input_str: str) -> str:
        """
        当用户浏览房源后，记录用户行为数据
        输入格式：用户id,房源id,数量,行为类型(浏览/收藏)
        例如：1001,2003,1,浏览
        """
        try:
            user_id, house_id, count, action = input_str.split(',')
            
            if not os.path.exists(DATA_FILE):
                df = pd.DataFrame(columns=['userid', 'houseid', 'count', 'action'])
                df.to_csv(DATA_FILE, index=False)
            
            new_data = pd.DataFrame({
                'userid': [user_id],
                'houseid': [house_id],
                'count': [count],
                'action': [action]
            })
            
            new_data.to_csv(DATA_FILE, mode='a', header=False, index=False)
            
            return f"成功记录用户{user_id}对房源{house_id}的{action}行为，数量{count}"
        except Exception as e:
            return f"数据收集失败: {str(e)}。请使用格式：用户id,房源id,数量,行为类型"

    @staticmethod
    @tool
    def calculate_similarity(input_str: str) -> str:
        """
        分析用户相似度，获取最相似的前10个用户
        输入格式：目标用户id
        例如：1001
        """
        try:
            user_id = input_str.strip()
            
            if not os.path.exists(DATA_FILE):
                return "暂无用户行为数据，无法计算相似度"
            
            df = pd.read_csv(DATA_FILE)
            df['weight'] = df['action'].map({'收藏': 5, '浏览': 1}).fillna(1)
            
            user_item_matrix = df.pivot_table(
                index='userid', 
                columns='houseid', 
                values='weight', 
                aggfunc='sum', 
                fill_value=0
            )
            
            similarity_matrix = cosine_similarity(user_item_matrix)
            np.fill_diagonal(similarity_matrix, 0)
            
            if int(user_id) not in user_item_matrix.index:
                return f"用户{user_id}不存在于数据中"
            
            user_idx = user_item_matrix.index.get_loc(int(user_id))
            similar_indices = np.argsort(similarity_matrix[user_idx])[::-1][:10]
            similar_users = user_item_matrix.index[similar_indices].tolist()
            similarity_scores = similarity_matrix[user_idx][similar_indices].tolist()
            
            similarity_data = {
                user_id: {
                    'similar_users': similar_users,
                    'scores': similarity_scores,
                    'timestamp': int(time.time())
                }
            }
            
            with open(SIMILARITY_CACHE, 'w') as f:
                json.dump(similarity_data, f)
            
            result = [f"用户{similar_users[i]}: 相似度{similarity_scores[i]:.4f}" 
                     for i in range(len(similar_users))]
            return f"与用户{user_id}最相似的10个用户：\n" + "\n".join(result)
        
        except Exception as e:
            return f"相似度计算失败: {str(e)}"

    @staticmethod
    @tool
    def recommend_houses(input_str: str) -> str:
        """
        基于用户相似度为用户推荐房源
        输入格式：目标用户id,推荐数量(可选，默认为5)
        例如：1001,8
        """
        try:
            params = input_str.split(',')
            user_id = params[0].strip()
            num_recommendations = int(params[1].strip()) if len(params) > 1 else 5
            
            if not os.path.exists(SIMILARITY_CACHE):
                return "请先计算用户相似度"
            
            with open(SIMILARITY_CACHE, 'r') as f:
                similarity_data = json.load(f)
            
            if user_id not in similarity_data:
                return f"没有用户{user_id}的相似度数据，请先计算"
            
            similar_users = similarity_data[user_id]['similar_users']
            
            if not os.path.exists(DATA_FILE):
                return "暂无用户行为数据，无法生成推荐"
            
            df = pd.read_csv(DATA_FILE)
            user_items = set(df[df['userid'] == int(user_id)]['houseid'].tolist())
            recommendations = {}
            
            for similar_user in similar_users:
                similar_user_items = df[df['userid'] == int(similar_user)]
                
                for _, item in similar_user_items.iterrows():
                    if item['houseid'] not in user_items:
                        similarity_score = next(
                            score for idx, score in enumerate(similarity_data[user_id]['scores'])
                            if similar_users[idx] == similar_user
                        )
                        
                        action_weight = 5 if item['action'] == '收藏' else 1
                        recommendation_score = similarity_score * action_weight * item['count']
                        
                        if item['houseid'] in recommendations:
                            recommendations[item['houseid']] += recommendation_score
                        else:
                            recommendations[item['houseid']] = recommendation_score
            
            sorted_recommendations = sorted(
                recommendations.items(), 
                key=lambda x: x[1], 
                reverse=True
            )[:num_recommendations]
            
            result = [
                {
                    'house_id': house_id,
                    'score': float(score)
                }
                for house_id, score in sorted_recommendations
            ]
            
            return result
        
        except Exception as e:
            return f"房源推荐失败: {str(e)}"

    def get_agent(self):
        """获取初始化的agent"""
        tools = [
            Tool(
                name="collect_house_data",
                func=self.collect_house_data,
                description="记录用户浏览房源数据"
            ),
            Tool(
                name="calculate_similarity",
                func=self.calculate_similarity,
                description="计算用户相似度"
            ),
            Tool(
                name="recommend_houses",
                func=self.recommend_houses,
                description="推荐房源"
            )
        ]
        
        return initialize_agent(
            tools,
            llm,
            agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
            verbose=True
        ) 